#pragma once
#include <string>
#include <cstdio>
#include <time.h>
#include <iostream>
#include<unistd.h>
#include<sys/types.h>
#include<cstdarg>
#include<pthread.h>
#include<fstream>
#include<cerrno>
bool gIsSave=false;
const std::string logname="log.txt";
// 日志是有等级的
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
void SaveFile(const std::string& logname,const std::string &message)
{
    std::ofstream out(logname,std::ios::app);
    if(!out.is_open())
    {
        return;
    }
    out<<message;
    out.close();
}
std::string LevelTostring(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARNING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        break;
    }
    return nullptr;
}

std::string GetTimeString()
{
    time_t curr_time = time(nullptr);
    struct tm *format_time = localtime(&curr_time);
    if (format_time == nullptr)
        return "None";
    char time_buffer[1024];
    snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d %d:%d:%d",
                                 format_time->tm_year+1900,
                                 format_time->tm_mon+1,
                                 format_time->tm_mday,
                                 format_time->tm_hour,
                                 format_time->tm_min,
                                 format_time->tm_sec
                                 );
                                 return time_buffer;
}
// 日志是有格式的
// 日志等级 时间 代码所在的文章名/行数  日志的内容

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
void LogMessage(std::string filename,int line,bool issave,int level, const char *format, ...)
{
    std::string levelstr = LevelTostring(level);
    std::string timestr = GetTimeString();
    pid_t selfid=getpid();

    char buffer[4096];
    va_list arg;
    va_start(arg,format);
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);
    std::string message=levelstr+" : "+timestr+" : "+filename+" : "+std::to_string(selfid)+" : "+std::to_string(line)+" : "+buffer+"\n";
    pthread_mutex_lock(&lock);
    if(!issave){
    std::cout<<levelstr<<" : "<<timestr<<" : "<<filename<<" : "<<selfid<<" : "<<line<<" : "<<buffer<<std::endl;
    }
    else{
        SaveFile(logname,message);
    }
     pthread_mutex_unlock(&lock);
}


#define LOG(level,format,...) do{LogMessage(__FILE__,__LINE__,gIsSave, level,format,##__VA_ARGS__);}while(0)
#define EnableFile() do{gIsSave=true;}while(0)
#define EnableScreen() do{gIsSave=false;}while(0)